package com.coocaa.typhoon.api.base.util;

import lombok.experimental.UtilityClass;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.FatalBeanException;
import org.springframework.util.ClassUtils;

import javax.validation.constraints.NotNull;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * @author bijiahao
 * @date : 2023/8/23 16:26
 * @description
 */
@UtilityClass
public class BeanMergeUtil {
    /**
     * 合并对象的字段，以第一个对象为主
     *
     * @param obj1
     * @param obj2
     */
    public static void merge(@NotNull Object obj1, Object obj2) {
        if (null == obj2) {
            return;
        }
        Class<?> actualEditable = obj2.getClass();
        PropertyDescriptor[] obj2Pds = BeanUtils.getPropertyDescriptors(actualEditable);
        PropertyDescriptor[] var7 = obj2Pds;
        int var8 = obj2Pds.length;

        for (int var9 = 0; var9 < var8; ++var9) {
            PropertyDescriptor obj2Pd = var7[var9];
            Method writeMethod = obj2Pd.getWriteMethod();
            if (writeMethod != null) {
                PropertyDescriptor obj1Pd = BeanUtils.getPropertyDescriptor(obj1.getClass(), obj2Pd.getName());
                if (obj1Pd != null) {
                    Method readMethod = obj1Pd.getReadMethod();
                    if (readMethod != null && ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
                        try {
                            if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
                                readMethod.setAccessible(true);
                            }
                            if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
                                writeMethod.setAccessible(true);
                            }
                            Object value1 = readMethod.invoke(obj1);
                            Object value2 = readMethod.invoke(obj2);
                            if (value1 == null && null != value2) {
                                writeMethod.invoke(obj1, value2);
                            }
                        } catch (Throwable var15) {
                            throw new FatalBeanException("Could not copy property '" + obj2Pd.getName() + "' from obj1 to obj2", var15);
                        }
                    }
                }
            }
        }
    }
}
